package com.yc.cloud.openai.portal.config;

import cn.hutool.core.util.ArrayUtil;
import lombok.val;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.ApiSelectorBuilder;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

/**
 * Swagger基础配置
 * Created by macro on 2020/7/16.
 */
public abstract class BaseSwaggerConfig {

    @Bean
    public Docket createRestApi() {
        SwaggerProperties swaggerProperties = swaggerProperties();
        ApiSelectorBuilder builder = new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo(swaggerProperties))
                .select();

        //如果传入多个包名
        String[] basePackages = swaggerProperties.getApiBasePackage().split(",");
        Predicate<RequestHandler> predicate = RequestHandlerSelectors.basePackage(basePackages[0]);
        if (swaggerProperties.getApiBasePackage().contains(",")) {
            for (int i = 1; i < basePackages.length; i++) {
                predicate = predicate.or(RequestHandlerSelectors.basePackage(basePackages[i].trim()));
            }
        }
        builder.apis(predicate);

        val docket = builder.build();

        //不需要权限认证的接口
        if (ArrayUtil.isNotEmpty(swaggerProperties.getExcludePath())) {
            swaggerProperties.getExcludePath().forEach(p -> builder.paths(PathSelectors.ant(p).negate()));
        }
        if (swaggerProperties.getGlobalResponseMessage() != null && swaggerProperties.getGlobalResponseMessage().size() > 0) {
            docket.globalResponses(HttpMethod.GET, swaggerProperties.getGlobalResponseMessage())
                    .globalResponses(HttpMethod.POST, swaggerProperties.getGlobalResponseMessage());
        }
        if (swaggerProperties.isEnableSecurity()) {
            docket.securitySchemes(securitySchemes()).securityContexts(securityContexts());
        }
        return docket;
    }

    private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {
        return new ApiInfoBuilder()
                .title(swaggerProperties.getTitle())
                .description(swaggerProperties.getDescription())
                .contact(new Contact(swaggerProperties.getContactName(), swaggerProperties.getContactUrl(), swaggerProperties.getContactEmail()))
                .version(swaggerProperties.getVersion())
                .build();
    }

    private List<SecurityScheme> securitySchemes() {
        //设置请求头信息
        List<SecurityScheme> result = new ArrayList<>();
        SecurityScheme apiKey = new ApiKey("Authorization", "Authorization", "header");
        result.add(apiKey);
        return result;
    }

    private List<SecurityContext> securityContexts() {
        //设置需要登录认证的路径
//        List<SecurityContext> result = new ArrayList<>();
//        //result.add(getContextByPath("/*/.*"));
//        result.add(getContextByPath("^(?!auth).*$"));
//        return result;


        List<SecurityContext> securityContexts = new ArrayList<>();
//通过PathSelectors.regex("^(?!/auth).*$")，排除包含"/auth"的接口不需要使用securitySchemes
        securityContexts.add(
                SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .operationSelector(operationContext ->
                                operationContext.requestMappingPattern().matches("^(?!/auth).*$")
                        )
                        .build());
        return securityContexts;
    }

    private SecurityContext getContextByPath(String pathRegex) {
        return SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.regex(pathRegex))
                .build();
    }

    private List<SecurityReference> defaultAuth() {
        List<SecurityReference> result = new ArrayList<>();
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        result.add(new SecurityReference("Authorization", authorizationScopes));
        return result;
    }


    /**
     * 自定义Swagger配置
     */
    public abstract SwaggerProperties swaggerProperties();

    public static void main(String[] args) {
        String mapping = "/auth/login";
        String mapping2 = "/sys-user/create";
        boolean m1 = mapping.matches("^(?!/auth).*$");
        boolean m2 = mapping2.matches("^(?!/auth).*$");
        System.out.println("m1=" + m1 + ",m2=" + m2);
    }
}
